package cn.sgjk.train.business.service;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.sgjk.train.business.controller.ConfirmOrderController;
import cn.sgjk.train.business.domain.ConfirmOrder;
import cn.sgjk.train.business.dto.ConfirmOrderMQDto;
import cn.sgjk.train.business.enums.ConfirmOrderStatusEnum;
import cn.sgjk.train.business.enums.RedisKeyEnum;
import cn.sgjk.train.business.enums.RocketMqTopicEnum;
import cn.sgjk.train.business.mapper.ConfirmOrderMapper;
import cn.sgjk.train.business.req.ConfirmOrderDoReq;
import cn.sgjk.train.business.req.ConfirmOrderTicketReq;
import cn.sgjk.train.common.context.LoginMemberContext;
import cn.sgjk.train.common.exception.BusinessException;
import cn.sgjk.train.common.exception.BusinessExceptionEnum;
import cn.sgjk.train.common.util.SnowUtil;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.jboss.logging.MDC;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class BeforeConfirmOrderService {
    private static final Logger LOG = LoggerFactory.getLogger(BeforeConfirmOrderService.class);

    @Autowired
    private SkTokenService skTokenService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private ConfirmOrderMapper confirmOrderMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Value("${spring.profiles.active}")
    private String env;


    @SentinelResource(value = "doComfire",blockHandler = "doComfireBlock")
    public Long beforeDoConfirm(ConfirmOrderDoReq confirmOrderDoReq)  {

            boolean getvalidSkToken = skTokenService.validSkToken(confirmOrderDoReq.getDate(),
                    confirmOrderDoReq.getTrainCode(),
                    LoginMemberContext.getId());

            if (getvalidSkToken) {
                LOG.info("令牌校验通过");
            } else {
                LOG.info("令牌校验不通过");
                throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_SK_TOKENB_FAIL);
            }
        confirmOrderDoReq.setMemberId(LoginMemberContext.getId());

//        String seatType = "1".equals(confirmOrderDoReq.getTickets().get(0).getSeatTypeCode()) ? "1" : "2";
//        String isNotTicketKey = DateUtil.format(confirmOrderDoReq.getDate(), "yyyy-MM-dd")
//                + confirmOrderDoReq.getTrainCode() + seatType + "NotTicketKey";
//
//        boolean notRemian = isNotRemian(isNotTicketKey);
//        if (notRemian) {
//            throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_TICKET_COUNT_ERROR);
//        }


        // 请求进来后，先保存订单信息，再发MQ等待出票 不管结果有没有成功 也能够避免MQ数据丢失可重发
        ConfirmOrder confirmOrder = new ConfirmOrder();
        confirmOrder.setId(SnowUtil.getSnowflakeNextId());
        confirmOrder.setMemberId(LoginMemberContext.getId());
        Date date = confirmOrderDoReq.getDate();
        confirmOrder.setDate(date);
        String trainCode = confirmOrderDoReq.getTrainCode();
        confirmOrder.setTrainCode(trainCode);
        String start = confirmOrderDoReq.getStart();
        confirmOrder.setStart(start);
        String end = confirmOrderDoReq.getEnd();
        confirmOrder.setEnd(end);
        confirmOrder.setDailyTrainTicketId(confirmOrderDoReq.getDailyTrainTicketId());
        confirmOrder.setStatus(ConfirmOrderStatusEnum.INIT.getCode());
        confirmOrder.setCreateTime(new Date());
        confirmOrder.setUpdateTime(new Date());
        List<ConfirmOrderTicketReq> tickets = confirmOrderDoReq.getTickets();
        confirmOrder.setTickets(JSON.toJSONString(tickets));
        confirmOrderMapper.insert(confirmOrder);


        // 发送MQ排队购票
        //confirmOrderDoReq.setLogId(MDC.get("LOG_ID"));

        ConfirmOrderMQDto confirmOrderMQDto = new ConfirmOrderMQDto();
        confirmOrderMQDto.setLogId(MDC.get("LOG_ID"));
        confirmOrderMQDto.setTrainCode(trainCode);
        confirmOrderMQDto.setDate(date);
        String reqJson = JSON.toJSONString(confirmOrderMQDto);
        LOG.info("排队购票,发送mq开始,消息：{}",reqJson);
        rocketMQTemplate.convertAndSend(RocketMqTopicEnum.CONFIRM_ORDER.getCode(),reqJson);
        LOG.info("排队购票,发送mq结束,消息：{}",reqJson);

        return confirmOrder.getId();

    }

    private void doComfireBlockExpection(ConfirmOrderDoReq confirmOrderDoReq, BlockException e) {
        LOG.info("当前购票被限流:{}",e);
        throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_FOLW_EXCEPTION);
    }


    private boolean isNotRemian(String isNotTicketKey) {

        Object value = redisTemplate.opsForValue().get(isNotTicketKey);
        if(ObjectUtil.isNotNull(value)) {
            boolean isNotRemain = BooleanUtil.toBoolean(value.toString());
            LOG.info("余票标识:{}",isNotRemain);
            // 当票标识为卖完,不往下执行
            if(isNotRemain) {
                LOG.info("票卖完了");
                return true;

            }
        }
        return false;
    }
}

